//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.jeecgframework.poi.excel.export;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.jeecgframework.poi.excel.annotation.ExcelTarget;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.excel.export.base.ExcelExportBase;
import org.jeecgframework.poi.excel.export.styler.IExcelExportStyler;
import org.jeecgframework.poi.exception.excel.ExcelExportException;
import org.jeecgframework.poi.exception.excel.enums.ExcelExportEnum;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.*;

public class ExcelExportServer extends ExcelExportBase {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExcelExportServer.class);
    private int MAX_NUM = 60000;

    public ExcelExportServer() {
    }

    private int createHeaderAndTitle(ExportParams entity, Sheet sheet, Workbook workbook, List<ExcelExportEntity> excelParams) {
        int rows = 0;
        int feildWidth = this.getFieldWidth(excelParams);
        if (entity.getTitle() != null) {
            rows += this.createHeaderRow(entity, sheet, workbook, feildWidth);
        }

        rows += this.createTitleRow(entity, sheet, workbook, rows, excelParams);
        sheet.createFreezePane(0, rows, 0, rows);
        return rows;
    }

    public int createHeaderRow(ExportParams entity, Sheet sheet, Workbook workbook, int feildWidth) {
        Row row = sheet.createRow(0);
        row.setHeight(entity.getTitleHeight());
        this.createStringCell(row, 0, entity.getTitle(), this.getExcelExportStyler().getHeaderStyle(entity.getHeaderColor()), (ExcelExportEntity) null);

        for (int i = 1; i <= feildWidth; ++i) {
            this.createStringCell(row, i, "", this.getExcelExportStyler().getHeaderStyle(entity.getHeaderColor()), (ExcelExportEntity) null);
        }

        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, feildWidth));
        if (entity.getSecondTitle() == null) {
            return 1;
        } else {
            row = sheet.createRow(1);
            row.setHeight(entity.getSecondTitleHeight());
            CellStyle style = workbook.createCellStyle();
            style.setAlignment((short) 3);
            this.createStringCell(row, 0, entity.getSecondTitle(), style, (ExcelExportEntity) null);

            for (int i = 1; i <= feildWidth; ++i) {
                this.createStringCell(row, i, "", this.getExcelExportStyler().getHeaderStyle(entity.getHeaderColor()), (ExcelExportEntity) null);
            }

            sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, feildWidth));
            return 2;
        }
    }

    public void createSheet(Workbook workbook, ExportParams entity, Class<?> pojoClass, Collection<?> dataSet, String[] exportFields) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Excel export start ,class is {}", pojoClass);
            LOGGER.debug("Excel version is {}", entity.getType().equals(ExcelType.HSSF) ? "03" : "07");
        }

        if (workbook != null && entity != null && pojoClass != null && dataSet != null) {
            super.type = entity.getType();
            if (this.type.equals(ExcelType.XSSF)) {
                this.MAX_NUM = 1000000;
            }

            Sheet sheet = null;

            try {
                sheet = workbook.createSheet(entity.getSheetName());
            } catch (Exception var19) {
                sheet = workbook.createSheet();
            }

            try {
                this.dataHanlder = entity.getDataHanlder();
                if (this.dataHanlder != null) {
                    this.needHanlderList = Arrays.asList(this.dataHanlder.getNeedHandlerFields());
                }

                this.setExcelExportStyler((IExcelExportStyler) entity.getStyle().getConstructor(Workbook.class).newInstance(workbook));
                Drawing patriarch = sheet.createDrawingPatriarch();
                List<ExcelExportEntity> excelParams = new ArrayList();
                if (entity.isAddIndex()) {
                    excelParams.add(this.indexExcelEntity(entity));
                }

                Field[] fileds = PoiPublicUtil.getClassFields(pojoClass);
                if (exportFields != null) {
                    List<Field> list = new ArrayList(Arrays.asList(fileds));

                    for (int i = 0; i < list.size(); ++i) {
                        if (!Arrays.asList(exportFields).contains(((Field) list.get(i)).getName())) {
                            list.remove(i);
                            --i;
                        }
                    }

                    if (list != null && list.size() > 0) {
                        fileds = (Field[]) list.toArray(new Field[0]);
                    } else {
                        fileds = null;
                    }
                }

                ExcelTarget etarget = (ExcelTarget) pojoClass.getAnnotation(ExcelTarget.class);
                String targetId = etarget == null ? null : etarget.value();
                this.getAllExcelField(entity.getExclusions(), targetId, fileds, excelParams, pojoClass, (List) null);
                this.reConfigExcelExportParams(excelParams, entity);
                int index = entity.isCreateHeadRows() ? this.createHeaderAndTitle(entity, sheet, workbook, excelParams) : 0;
                this.setCellWith(excelParams, sheet);
                short rowHeight = this.getRowHeight(excelParams);
                this.setCurrentIndex(1);
                Iterator<?> its = dataSet.iterator();
                ArrayList tempList = new ArrayList();

                while (its.hasNext()) {
                    Object t = its.next();
                    index += this.createCells(patriarch, index, t, excelParams, sheet, workbook, rowHeight);
                    tempList.add(t);
                    if (index >= this.MAX_NUM) {
                        break;
                    }
                }

                this.mergeCells(sheet, excelParams, index);
                if (entity.getFreezeCol() != 0) {
                    sheet.createFreezePane(entity.getFreezeCol(), 0, entity.getFreezeCol(), 0);
                }

                its = dataSet.iterator();
                int i = 0;

                for (int le = tempList.size(); i < le; ++i) {
                    its.next();
                    its.remove();
                }

                this.addStatisticsRow(this.getExcelExportStyler().getStyles(true, (ExcelExportEntity) null), sheet);
                if (dataSet.size() > 0) {
                    this.createSheet(workbook, entity, pojoClass, dataSet, exportFields);
                }

            } catch (Exception var20) {
                LOGGER.error(var20.getMessage(), var20);
                throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, var20.getCause());
            }
        } else {
            throw new ExcelExportException(ExcelExportEnum.PARAMETER_ERROR);
        }
    }

    public void createSheetForMap(Workbook workbook, ExportParams entity, List<ExcelExportEntity> entityList, Collection<? extends Map<?, ?>> dataSet) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Excel version is {}", entity.getType().equals(ExcelType.HSSF) ? "03" : "07");
        }

        if (workbook != null && entity != null && entityList != null && dataSet != null) {
            super.type = entity.getType();
            if (this.type.equals(ExcelType.XSSF)) {
                this.MAX_NUM = 1000000;
            }

            Sheet sheet = null;

            try {
                sheet = workbook.createSheet(entity.getSheetName());
            } catch (Exception var15) {
                sheet = workbook.createSheet();
            }

            try {
                this.dataHanlder = entity.getDataHanlder();
                if (this.dataHanlder != null) {
                    this.needHanlderList = Arrays.asList(this.dataHanlder.getNeedHandlerFields());
                }

                this.setExcelExportStyler((IExcelExportStyler) entity.getStyle().getConstructor(Workbook.class).newInstance(workbook));
                Drawing patriarch = sheet.createDrawingPatriarch();
                List<ExcelExportEntity> excelParams = new ArrayList();
                if (entity.isAddIndex()) {
                    excelParams.add(this.indexExcelEntity(entity));
                }

                excelParams.addAll(entityList);
                this.sortAllParams(excelParams);
                int index = entity.isCreateHeadRows() ? this.createHeaderAndTitle(entity, sheet, workbook, excelParams) : 0;
                this.setCellWith(excelParams, sheet);
                short rowHeight = this.getRowHeight(excelParams);
                this.setCurrentIndex(1);
                Iterator<?> its = dataSet.iterator();
                ArrayList tempList = new ArrayList();

                while (its.hasNext()) {
                    Object t = its.next();
                    index += this.createCells(patriarch, index, t, excelParams, sheet, workbook, rowHeight);
                    tempList.add(t);
                    if (index >= this.MAX_NUM) {
                        break;
                    }
                }

                if (entity.getFreezeCol() != 0) {
                    sheet.createFreezePane(entity.getFreezeCol(), 0, entity.getFreezeCol(), 0);
                }

                this.mergeCells(sheet, excelParams, index);
                its = dataSet.iterator();
                int i = 0;

                for (int le = tempList.size(); i < le; ++i) {
                    its.next();
                    its.remove();
                }

                if (dataSet.size() > 0) {
                    this.createSheetForMap(workbook, entity, entityList, dataSet);
                }

            } catch (Exception var16) {
                LOGGER.error(var16.getMessage(), var16);
                throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, var16.getCause());
            }
        } else {
            throw new ExcelExportException(ExcelExportEnum.PARAMETER_ERROR);
        }
    }

    private int createTitleRow(ExportParams title, Sheet sheet, Workbook workbook, int index, List<ExcelExportEntity> excelParams) {
        Row row = sheet.createRow(index);
        int rows = this.getRowNums(excelParams);
        row.setHeight((short) 450);
        Row listRow = null;
        if (rows == 2) {
            listRow = sheet.createRow(index + 1);
            listRow.setHeight((short) 450);
        }

        int cellIndex = 0;
        CellStyle titleStyle = this.getExcelExportStyler().getTitleStyle(title.getColor());
        int i = 0;

        for (int exportFieldTitleSize = excelParams.size(); i < exportFieldTitleSize; ++i) {
            ExcelExportEntity entity = (ExcelExportEntity) excelParams.get(i);
            List sTitel;
            if (entity.isColspan()) {
                sTitel = entity.getSubColumnList();
                if (sTitel == null || sTitel.size() == 0) {
                    continue;
                }

                entity.initSubExportEntity(excelParams);
            }

            if (StringUtils.isNotBlank(entity.getName())) {
                this.createStringCell(row, cellIndex, entity.getName(), titleStyle, entity);
            }

//            CreationHelper creationHelper = wb.getCreationHelper();
//            if (StringUtils.isNotBlank(entity.getNotes())) {
//                ClientAnchor anchor = creationHelper.createClientAnchor();
//                anchor.setCol1(cell.getColumnIndex());
//                anchor.setCol2(cell.getColumnIndex() + 3);
//                anchor.setRow1(cell.getRowIndex() + 1);
//                anchor.setRow2(cell.getRowIndex() + 4);
//                Comment comment = drawing.createCellComment(anchor);
//                comment.setString(creationHelper.createRichTextString(columnInfo.annotation.notes()));
//                comment.setVisible(false);
//                cell.setCellComment(comment);
//            }

            if (entity.isPullDown() && entity.getOldReplace() != null) {
                String baseName = this.createRefSheetWithNames(workbook, entity, titleStyle);

                DataValidationConstraint dvc = sheet.getDataValidationHelper()
                        .createFormulaListConstraint(baseName);
                CellRangeAddressList range = new CellRangeAddressList(rows + 1, this.MAX_NUM, cellIndex, cellIndex);
                sheet.addValidationData(sheet.getDataValidationHelper().createValidation(dvc, range));
            }

            if (entity.getList() != null) {
                sTitel = entity.getList();
                if (StringUtils.isNotBlank(entity.getName())) {
                    sheet.addMergedRegion(new CellRangeAddress(index, index, cellIndex, cellIndex + sTitel.size() - 1));
                }

                int j = 0;

                for (int size = sTitel.size(); j < size; ++j) {
                    this.createStringCell(rows == 2 ? listRow : row, cellIndex, ((ExcelExportEntity) sTitel.get(j)).getName(), titleStyle, entity);
                    if (((ExcelExportEntity) sTitel.get(j)).isPullDown() && ((ExcelExportEntity) sTitel.get(j)).getOldReplace() != null) {
                        String baseName = this.createRefSheetWithNames(workbook, ((ExcelExportEntity) sTitel.get(j)), titleStyle);
                        DataValidationConstraint dvc = sheet.getDataValidationHelper().createFormulaListConstraint(baseName);
                        CellRangeAddressList range = new CellRangeAddressList(rows + 1, this.MAX_NUM, cellIndex, cellIndex);
                        sheet.addValidationData(sheet.getDataValidationHelper().createValidation(dvc, range));
                    }
                    ++cellIndex;
                }

                --cellIndex;
            } else if (rows == 2) {
                this.createStringCell(listRow, cellIndex, "", titleStyle, entity);
                sheet.addMergedRegion(new CellRangeAddress(index, index + 1, cellIndex, cellIndex));
            }

            ++cellIndex;
        }

        return rows;
    }


    /**
     * 创建关联sheet页（隐藏）及相关的“名称”（Excel名称管理器中的那种）
     */
    private String createRefSheetWithNames(Workbook wb, ExcelExportEntity entity, CellStyle titleStyle) {

        String baseName = "REF_" + entity.getReplaceKey();
        if (wb.getName(baseName) == null) {
            // 创建REF sheet
            Sheet sheet = wb.getSheet("REF");
            if (sheet == null) {
                sheet = wb.createSheet("REF");
                wb.setSheetHidden(wb.getSheetIndex(sheet), true);
            }

            // 创建全集引用Name
            int rowNum = sheet.getLastRowNum() + 1;
            Row row = sheet.createRow(rowNum);
            int cellNum = 0;
            for (String value : entity.getOldReplace()) {
                this.createStringCell(row, cellNum, value, titleStyle, entity);
                cellNum++;
            }
            Name wbName = wb.createName();
            wbName.setNameName(baseName);
            wbName.setRefersToFormula(
                    "REF!" + "$A$" + (rowNum + 1) + ":$" + numberToColumnHead(cellNum) + "$" + (rowNum + 1));
            rowNum++;

//            // 创建级联引用的Name
//            Map<String, List<ExcelColumnSelectionItem>> map = new LinkedHashMap<String, List<ExcelColumnSelectionItem>>();
//            for (ExcelColumnSelectionItem selectionItem : columnInfo.getSelectionItems()) {
//                String refName = selectionItem.getRefName();
//                if (Utils.isNotBlank(refName)) {
//                    List<ExcelColumnSelectionItem> list = map.get(refName);
//                    if (list == null) {
//                        list = new ArrayList<ExcelColumnSelectionItem>();
//                        map.put(refName, list);
//                    }
//                    list.add(selectionItem);
//                }
//            }
//            for (Map.Entry<String, List<ExcelColumnSelectionItem>> entry : map.entrySet()) {
//                String refName = entry.getKey();
//                List<ExcelColumnSelectionItem> list = entry.getValue();
//                row = sheet.createRow(rowNum);
//                cellNum = 0;
//                for (ExcelColumnSelectionItem item : list) {
//                    Cell cell = row.createCell(cellNum, CellType.STRING);
//                    cell.setCellValue(item.getName());
//                    cellNum++;
//                }
//                wbName = wb.createName();
//                wbName.setNameName(baseName + "_" + refName);
//                wbName.setRefersToFormula(
//                        "REF!" + "$A$" + (rowNum + 1) + ":$" + numberToColumnHead(cellNum) + "$" + (rowNum + 1));
//                rowNum++;
//            }
        }
        return baseName;
    }

    /**
     * 数字转换为Excel列头格式，如1转换为A，2转换为B，27转换为AA等
     */
    private String numberToColumnHead(int num) {
        if (num <= 26) {
            return String.valueOf((char) ('A' + (num - 1)));
        } else {
            int h = (num - 1) / 26;
            int l = (num - 1) % 26 + 1;
            return numberToColumnHead(h) + numberToColumnHead(l);
        }
    }

    private int getRowNums(List<ExcelExportEntity> excelParams) {
        for (int i = 0; i < excelParams.size(); ++i) {
            ExcelExportEntity temp = (ExcelExportEntity) excelParams.get(i);
            if ((temp.getList() != null || temp.isColspan()) && StringUtils.isNotBlank(temp.getName())) {
                return 2;
            }
        }

        return 1;
    }

    private ExcelExportEntity indexExcelEntity(ExportParams entity) {
        ExcelExportEntity exportEntity = new ExcelExportEntity();
        exportEntity.setOrderNum(0);
        exportEntity.setName(entity.getIndexName());
        exportEntity.setWidth(10.0D);
        exportEntity.setFormat("isAddIndex");
        return exportEntity;
    }
}
